<template>
  <div>
    <div class="row">
      <form @submit.prevent="connected ? disconnect() : connect()">
        <div class="form-group col-xs-12 col-sm-4">
          <div class="input-group">
            <span class="input-group-addon">Name</span>
            <input type="text" class="form-control" v-model="name" :readonly="connected">
          </div>
        </div>
        <div class="form-group col-xs-12 col-sm-6">
          <div class="input-group" v-if="connected">
            <span class="input-group-addon">URL</span>
            <div class="form-control" readonly>{{host}}:{{port}}</div>
          </div>
          <div class="input-group" v-else>
            <span class="input-group-addon">Port</span>
            <input type="text" class="form-control" v-model="port">
          </div>
        </div>
        <div class="form-group col-xs-12 col-sm-2">
          <button type="submit" class="btn btn-{{connected ? 'warning' : 'success'}} btn-block">
            {{connected ? 'Disc' : 'C'}}onnect
          </button>
        </div>
      </form>
      <div class="col-xs-12 col-sm-4">
        <h4>Clients</h4>
        <ul class="list-group">
          <li class="list-group-item" v-for="c in clients">
            {{c}}
          </li>
        </ul>
      </div>
      <form class="col-xs-12 col-sm-8" @submit.prevent="publish">
        <h4>Publish</h4>
        <div class="form-group">
          <div class="input-group">
            <span class="input-group-addon">Topic</span>
            <input type="text" class="form-control" v-model="newMsg.topic" :disabled="!connected" required>
          </div>
        </div>
        <div class="form-group">
          <div class="input-group">
            <span class="input-group-addon">Message</span>
            <textarea rows="3" class="form-control" v-model="newMsg.payload" :disabled="!connected"></textarea>
          </div>
        </div>
        <div class="row">
          <div class="form-group col-xs-12 col-sm-6">
            <div class="input-group">
              <span class="input-group-addon">Qos</span>
              <select class="form-control" v-model="newMsg.qos" :disabled="!connected">
                <option v-for="q in [0, 1, 2]" :value="q">
                  {{q}}
                </option>
              </select>
            </div>
          </div>
          <div class="form-group col-xs-12 col-sm-3">
            <button type="button" class="btn btn-default btn-block" :disabled="!connected" @click="clear">
              Clear
            </button>
          </div>
          <div class="form-group col-xs-12 col-sm-3">
            <button type="submit" class="btn btn-info btn-block" :disabled="!connected">
              Publish
            </button>
          </div>
        </div>
      </form>
    </div>
    <h4>{{name}} Logs</h4>
    <msg :msgs="msgs"></msg>
  </div>
</template>

<script>
const Utils = require('../utils');
const each = Utils.each;
const pick = Utils.pick;
const stringify = Utils.stringify;
const isString = Utils.isString;

const Msg = require('./msg');

const clientConnectedRE = /^Client connected\: (.+)$/;
const clientDisonnectedRE = /^Client disconnected\: (.+)$/;

exports.props = [
  'mqtt',
  'name'
];

exports.components = {
  Msg
};

let lastPort = ~~(Math.random() * 35000) + 30000;
exports.data = () => {
  return {
    host: window.location.hostname,
    port: ++lastPort,
    connected: false,
    msgs: [],
    clients: [],
    newMsg: {
      topic: '',
      payload: '',
      qos: 0
    }
  };
};

exports.methods = {
  cmd(cmd, options) {
    return this.mqtt.publish(stringify({
      type: 'server',
      name: this.name,
      cmd
    }), stringify(options), {
      qos: 2
    });
  },
  server() {
    const topic = pick(this, [
      'name',
      'port'
    ]);
    topic.type = 'server';

    return stringify(topic);
  },
  connect() {
    const _this = this;
    _this.mqtt.subscribe(_this.server(), {
      qos: 2
    }, () => {
      _this.connected = true;
    });
  },
  disconnect() {
    const _this = this;
    _this.mqtt.unsubscribe(_this.server(), () => {
      _this.connected = false;
    });
  },
  publish() {
    const _this = this;
    _this.cmd('publish', _this.newMsg);
  },
  clear() {
    const _this = this;
    each(_this.newMsg, (v, k) => isString(v) && (_this.newMsg[k] = ''));
  }
};

let count = 0;
exports.created = function() {
  const _this = this;
  _this.name = `Server ${++count}`;

  _this.$on('server', (msg) => {
    if (msg.name == _this.name) {
      _this.msgs.unshift(msg);

      const text = msg.msg;
      const clients = _this.clients;
      let client;
      let index;
      if (clientConnectedRE.test(text)) {
        client = clientConnectedRE.exec(text)[1];
        clients.indexOf(client) < 0 && clients.push(client);
      } else if (clientDisonnectedRE.test(text)) {
        client = clientDisonnectedRE.exec(text)[1];
        index = clients.indexOf(client);
        index > -1 && clients.splice(index, 1);
      }
    }
  });
};

exports.beforeDestroy = function() {
  this.disconnect();
};
</script>

<style lang="stylus">
</style>
